package com.bwbear.db.splitdb.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.bwbear.db.splitdb.utils.MapUtils;
import com.bwbear.db.splitdb.utils.PassWordUtils;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.support.StandardServletEnvironment;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;

/**
 * @author 张照威
 * @date 2020/8/20
 * @mail 865533614@qq.com
 * @describe
 */
@Configuration
public abstract class MyBatiesPlusConfiguration {

    @Value("${bwbear.db.path}")
    private String dbPath;

    @Autowired
    private Environment environment;

    /**
     * 分页插件，自动识别数据库类型
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }

    /**
     * SQL执行效率插件
     * 设置 dev test 环境开启
     */
    @Bean
    @Profile({"dev", "qa"})
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1000);
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }

//    @Bean(name = "ahhy")
//    @ConfigurationProperties(prefix = "spring.datasource.druid.ahhy")
//    public DataSource ahhyDb() {
//        return DruidDataSourceBuilder.create().build();
//    }
//
//    @Bean(name = "qdhm")
//    @ConfigurationProperties(prefix = "spring.datasource.druid.qdhm")
//    public DataSource qdhmDb() {
//        return DruidDataSourceBuilder.create().build();
//    }

    /**
     * 动态数据源配置
     *
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource() {
        MutablePropertySources mutablePropertySources = ((StandardServletEnvironment)environment).getPropertySources();
        Iterator<PropertySource<?>> iterator = mutablePropertySources.iterator();
        PropertySource<?> next = iterator.next();
        HashMap source = (LinkedHashMap)next.getSource();
        Map<String,DbConfig> map = MapUtils.mmm(source, DbConfig.class, dbPath, 1, "dbName");

        MultipleDataSource multipleDataSource = new MultipleDataSource();
        Map targetDataSources = new HashMap<>();
        map.forEach((k,v)->{
            Properties dbProperties = new Properties();
            dbProperties.setProperty("druid.driverClassName",v.getDriverClassName());
            dbProperties.setProperty("druid.name",v.getDbName());
            dbProperties.setProperty("druid.url",v.getUrl());
            dbProperties.setProperty("druid.username",v.getUsername());
            dbProperties.setProperty("druid.password", PassWordUtils.decrypt(v.getPassword()));
            v.setProperties(dbProperties);
            DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();
            druidDataSource.configFromPropety(dbProperties);
            try {
                druidDataSource.restart();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            targetDataSources.put(v.getDbName(),druidDataSource);

        });
        //添加数据源
        multipleDataSource.setTargetDataSources(targetDataSources);
        //设置默认数据源db1
//        multipleDataSource.setDefaultTargetDataSource(druidDataSource );
        multipleDataSource.setDefaultTargetDataSource(targetDataSources.get("base"));
        return multipleDataSource;
    }

    /**
     * 返回MybatisSqlSessionFactory
     *
     * @return
     * @throws Exception
     */
    @Bean
    public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean() throws IOException {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        this.globalConfig(sqlSessionFactory);
        sqlSessionFactory.setDataSource(this.multipleDataSource());
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setPlugins(new Interceptor[]{this.paginationInterceptor(), this.sqlInterceptor()});
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String mapperLocations1 = "classpath*:/com/gwfd/mes/app/*/*/mapper/**.xml";
        Resource[] resources1 = resolver.getResources(mapperLocations1);
        String mapperLocations2 = "classpath*:/online/bwbear/mybatisx/mapper/*";
        Resource[] resources2 = resolver.getResources(mapperLocations2);
        List<Resource> resourcesList = new ArrayList<Resource>(Arrays.asList(resources1));
        resourcesList.addAll(Arrays.asList(resources2));
        Resource[] resources = new Resource[resourcesList.size()];
        resourcesList.toArray(resources);
        sqlSessionFactory.setMapperLocations(resources);
        sqlSessionFactory.setTypeAliasesPackage("com.gwfd.mes.app.*.*.entity");
        return sqlSessionFactory;
    }

    protected abstract Interceptor sqlInterceptor();

    public abstract GlobalConfig globalConfig(MybatisSqlSessionFactoryBean sqlSessionFactory);
//    GlobalConfig globalConfig = new GlobalConfig();
//    //给global配置全局参数  任意插入或修改时的变量
//        globalConfig.setMetaObjectHandler(new DefaultFieldValueHandler() {
//        @Override
//        public void insertFill(MetaObject metaObject) {
//            //这里自定义 例子看抽象类注释
//        }
//
//        @Override
//        public void updateFill(MetaObject metaObject) {
//            //这里自定义 例子看抽象类注释
//        }
//    });
//    //给global设置sql注入器
////        globalConfig.setSqlInjector(new MySqlInjector());
////        //数据库配置, 默认即可
////        globalConfig.setDbConfig(dbConfig1);
//        return globalConfig;
}
